package c2.group.business.teampvp.sub;

import c2.group.business.base.GroupSubModule;
import c2.group.business.teampvp.TeamPvpModule;
import c2.group.business.teampvp.TeamPvpTeam;
import cate.common.util.GameResult;
import easy.java.dev.note.NoteField;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class TeamPvpTeamModule extends GroupSubModule<TeamPvpModule> {
    @NoteField("队伍数据")
    public Map<String, TeamPvpTeam> teams;
    @NoteField("<玩家uid,队伍uid>")
    public Map<String, String> teamPlayers;
    private final Object teamLock = new Object();

    @Override
    public void initDependent() {
        this.teams = useDb().teamPvp.getTeams();
        this.teams.entrySet().removeIf(e -> e.getValue().memberUids.isEmpty());
        this.teamPlayers = new ConcurrentHashMap<>();
        for (TeamPvpTeam team : teams.values()) {
            team.memberUids.forEach(e -> teamPlayers.put(e, team.uid));
        }
    }

    public void seasonReset() {
        synchronized (teamLock) {
            teamPlayers.clear();
            teams.clear();
        }
    }

    private GameResult<TeamPvpTeam> createTeam(String playerUid) {
        GameResult<TeamPvpTeam> r = new GameResult<>();
        if (teamPlayers.containsKey(playerUid)) {
            return r.f("您已经有队伍了");
        }
        TeamPvpTeam team = new TeamPvpTeam(playerUid);
        teams.put(team.uid, team);
        teamPlayers.put(playerUid, team.uid);
        r.data = team;
        return r;
    }

    private void removeMember(TeamPvpTeam team) {
        //一个人走了，队伍就没了
        team.memberUids.forEach(memberUid -> teamPlayers.remove(memberUid));
        teams.remove(team.uid);
    }

    private void addMember(TeamPvpTeam team, String inviteUid) {
        team.addMember(inviteUid);
        teamPlayers.put(inviteUid, team.uid);
    }

    public TeamPvpTeam findPlayerTeam(String playerUid) {
        synchronized (teamLock) {
            return getTeam(playerUid);
        }
    }

    private TeamPvpTeam getTeam(String playerUid) {
        if (StringUtils.isBlank(playerUid)) {
            return null;
        }
        String teamUid = teamPlayers.get(playerUid);
        if (StringUtils.isNotBlank(teamUid)) {
            return teams.get(teamUid);
        }
        return null;
    }

    public boolean hasTeam(String playerUid) {
        return StringUtils.isNotBlank(playerUid) && teamPlayers.containsKey(playerUid);
    }

    public GameResult<Void> invite(String leaderUid, String inviteUid) {
        GameResult<Void> r = new GameResult<>();
        synchronized (teamLock) {
            if (teamPlayers.containsKey(leaderUid)) {
                return r.fail("您已经有队伍了，无法再邀请其他玩家");
            }
            if (teamPlayers.containsKey(inviteUid)) {
                return r.fail("您邀请的玩家已经有队伍了");
            }
        }
        return r;
    }

    public GameResult<TeamPvpTeam> agreeInvite(String leaderUid, String inviteUid) {
        GameResult<TeamPvpTeam> r = new GameResult<>();
        TeamPvpTeam team;
        synchronized (teamLock) {
            team = getTeam(inviteUid);
            if (team != null && team.memberUids.size() > 1) {
                return r.fail("您已经有队伍辣");
            }
            team = getTeam(leaderUid);
            if (team != null && team.memberUids.size() > 1) {
                return r.fail("他/她的队伍已经满员辣");
            }
            if (parent.getFight().isFighting(leaderUid, team == null ? null : team.uid)) {
                return r.fail("他/她正在挑战中，请稍后再尝试");
            }
            if (team == null) {
                GameResult<TeamPvpTeam> createRes = createTeam(leaderUid);
                if (!createRes.ok()) {
                    return r.fail(createRes);
                }
                team = createRes.data;
            }
            if (team == null) {
                return r.fail("创建失败了噢，要不再试试呢");
            }
            addMember(team, inviteUid);
        }
        r.data = team;
        return r;
    }

    public GameResult<TeamPvpTeam> changeLeader(String leaderUid, String newLeaderUid) {
        GameResult<TeamPvpTeam> r = new GameResult<>();
        TeamPvpTeam team;
        synchronized (teamLock) {
            team = getTeam(leaderUid);
            if (team == null) {
                return r.fail("队伍不存在");
            }
            if (!StringUtils.equals(leaderUid, team.leaderUid)) {
                return r.fail("您不是队长，无法转让");
            }
            if (!team.memberUids.contains(newLeaderUid)) {
                return r.fail("他/她不在您的队伍中");
            }
            team.leaderUid = newLeaderUid;
        }
        r.data = team;
        return r;
    }

    public GameResult<Void> kickOut(String leaderUid, String toKickUid) {
        GameResult<Void> r = new GameResult<>();
        TeamPvpTeam team;
        synchronized (teamLock) {
            team = getTeam(leaderUid);
            if (team == null) {
                return r.fail("队伍不存在");
            }
            if (!StringUtils.equals(leaderUid, team.leaderUid)) {
                return r.fail("您不是队长，无法踢人");
            }
            if (!team.memberUids.contains(toKickUid)) {
                return r.fail("他/她不在您的队伍中，无法踢出队伍");
            }
            if (parent.getFight().isFighting(toKickUid, team.uid)) {
                return r.fail("挑战过程中，不允许踢出队伍");
            }
            removeMember(team);
        }
        return r;
    }

    public GameResult<TeamPvpTeam> exitTeam(String playerUid) {
        GameResult<TeamPvpTeam> r = new GameResult<>();
        TeamPvpTeam team;
        synchronized (teamLock) {
            team = getTeam(playerUid);
            if (team == null) {
                return r.fail("您没有队伍哦");
            }
            if (StringUtils.equals(playerUid, team.leaderUid)) {
                return r.fail("您是队长，请先转让后再退队");
            }
            if (parent.getFight().isFighting(playerUid, team.uid)) {
                return r.fail("挑战过程中，不允许退出队伍");
            }
            removeMember(team);
            r.data = team;
        }
        return r;
    }

    @Override
    public void onShutdown() throws Exception {
        super.onShutdown();
        saveTeams();
    }

    public void saveTeams() {
        synchronized (teamLock) {
            useDb().teamPvp.saveTeams(teams.values());
        }
    }
}
